package com.cwx.mychat.config;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;

/**
 * 作者： cwx
 * 时间： 2024/9/29 14:46
 * 版本： 1.0
 * 注释：
 */
public class MyRabbitMQConfig {

     @Resource
     private RabbitTemplate rabbitTemplate;

    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    /**
     * 定制RabbitTemplate
     * 1.服务收到消息就回调
     *     1.spring.rabbitmq.publisher-confirms=true
     *     2.设置确认回调ConfirmCallback
     * 2.消息正确抵达队列进行回调
     *     1. spring.rabbitmq.publisher-returns=ture
     *        spring.rabbitmq.template.mandatory=true
     *     2. 设置确认回调ReturnCallback
     * 3. 消费端确认（保证每个消息被正确消费，此时才可以broker删除这个消息）
     *      1. 默认是自动确认的， 只要消息接收到，客户端会自动确认，服务端就会移除这个消息
     *          问题： 我们收到很多消息的时候，自动回复给服务器ack，只有一个消息处理成功，宕机了。发送消息丢失
     *          解决方案：手动确认,开启手动确认后只要没有被确认，消息就会一直处于unacked状态。几十突然宕机。消息也不会丢失，会重新变为Ready状态等待下一次接收消息
     *      2.如何签收
     *          channel.basicAck(deliveryTag, false); 签收获取
     *          channel.basicNack(deliveryTag, false, false); 拒签
     */
    @PostConstruct  //MyRabbitConfig对象创建完成以后，执行这个方法
    public void initRabbitTemplate() {

     /**
     * 1、只要消息抵达Broker就ack=true
     * correlationData：当前消息的唯一关联数据(这个是消息的唯一id)
     * ack：消息是否成功收到
     * cause：失败的原因
     */
        //设置确认回调
        rabbitTemplate.setConfirmCallback((correlationData,ack,cause) -> {
            System.out.println("confirm...correlationData["+correlationData+"]==>ack:["+ack+"]==>cause:["+cause+"]");
        });


     /**
     * 只要消息没有投递给指定的队列，就触发这个失败回调
     * message：投递失败的消息详细信息
     * replyCode：回复的状态码
     * replyText：回复的文本内容
     * exchange：当时这个消息发给哪个交换机
     * routingKey：当时这个消息用哪个路邮键
     */
//        rabbitTemplate.setReturnCallback((message,replyCode,replyText,exchange,routingKey) -> {
//            System.out.println("Fail Message["+message+"]==>replyCode["+replyCode+"]" +
//                    "==>replyText["+replyText+"]==>exchange["+exchange+"]==>routingKey["+routingKey+"]");
//        });
    }
}
